package com.songcha.library_business.ui.view

import android.animation.Animator
import android.animation.ObjectAnimator
import android.animation.ValueAnimator
import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Bitmap
import android.graphics.Camera
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Matrix
import android.graphics.Paint
import android.graphics.Rect
import android.util.AttributeSet
import android.view.View
import android.view.animation.Animation.AnimationListener
import android.widget.ImageView
import androidx.annotation.Keep
import androidx.core.graphics.drawable.toBitmap
import androidx.core.graphics.times
import androidx.core.graphics.withMatrix
import com.songcha.library_business.R
import com.songcha.library_common.util.GlideUtil
import com.songcha.library_common.util.LogUtil
import com.songcha.library_common.util.ScreenUtil
import com.songcha.library_common.util.dp2px
import com.songcha.library_common.util.sp2px


@SuppressLint("AppCompatCustomView")
class BookOpenView
@JvmOverloads
constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyle: Int = 0,
    defRes: Int = 0
) : View(context,attrs,defStyle,defRes) {
    companion object{
        const val ANIM_DURATION=500L
    }


    interface IOnBookAnimationListener{
        fun onBookOpenAnimationEnd(bookId:String)
        fun onBookCloseAnimationEnd(bookId:String)
    }

    private var mValue=0f
    private var mBitmap:Bitmap?=null
    private var mImgWidth=0f
    private var mImgHeight=0f
    private var mImgLeft=0
    private var mImgTop=0
    private var mMinScaleWidth=1f
    private var mMinScaleHeight=1f
    private var mMaxScaleWidth=1f
    private var mMaxScaleHeight=1f
    private lateinit var mCamera:Camera
    private var mIsOpen=false
    private var mPageRect=Rect()
    private var mPagePaint=Paint()
    private var mMatrixValues= FloatArray(9)
    private var mCameraMatrix=Matrix()
    private var mBookId:String=""
    private var mListener:IOnBookAnimationListener?=null
    private var mPageBackgroundColor=Color.WHITE

    init {
        initView(context,attrs)
    }

    /***
     * anim of open book anim
     */
    fun initView(context: Context, attrs: AttributeSet?){
        if(attrs!=null){
            val ta=context.obtainStyledAttributes(attrs, R.styleable.BookOpenView)
            mPageBackgroundColor=ta.getColor(R.styleable.BookOpenView_book_open_page_background_color,Color.WHITE)
            ta.recycle()
        }

        mCamera=Camera()
        mPagePaint=Paint()
        mPagePaint.isAntiAlias=true
        mPagePaint.color=mPageBackgroundColor
    }

    /***
     * anim of close book
     */
    fun setOnBookAnimationListener(listener:IOnBookAnimationListener){
        mListener=listener
    }

    fun startBookOpenAnimation(bookId:String,img:ImageView,imgLeft:Int,imgTop:Int){
        mBookId=bookId
        mBitmap=img.drawable.toBitmap()
        mIsOpen=true

        mImgWidth=img.width.toFloat()
        mImgHeight=img.height.toFloat()
        mImgLeft=imgLeft
        mImgTop=imgTop
        //bitmap size is show image size,not origin image size
        mMinScaleWidth=mImgWidth/mBitmap!!.width
        mMinScaleHeight=mImgHeight/mBitmap!!.height
        mMaxScaleWidth=width/(mBitmap!!.width*1.0f)
        mMaxScaleHeight=height/(mBitmap!!.height*1.0f)
        mPageRect=Rect(0,0,mBitmap!!.width.toInt(),mBitmap!!.height.toInt())


        var anim:ValueAnimator=ValueAnimator.ofFloat(0f,1f)

        anim.duration=ANIM_DURATION
        anim.addUpdateListener {
            mValue=it.animatedValue as Float
            invalidate()
        }
        anim.addListener(object :Animator.AnimatorListener{
            override fun onAnimationStart(animation: Animator) {

            }

            override fun onAnimationEnd(animation: Animator) {
                mListener?.onBookOpenAnimationEnd(mBookId)
            }

            override fun onAnimationCancel(animation: Animator) {

            }

            override fun onAnimationRepeat(animation: Animator) {

            }
        })
        anim.start()
    }

    fun startBookCloseAnimation(){
        if(!mIsOpen || mBitmap==null || mBookId.isBlank()) return

        var anim:ValueAnimator=ValueAnimator.ofFloat(1f,0f)

        anim.duration=ANIM_DURATION
        anim.addUpdateListener {
            mValue=it.animatedValue as Float
            invalidate()
        }
        anim.addListener(object :Animator.AnimatorListener{
            override fun onAnimationStart(animation: Animator) {

            }

            override fun onAnimationEnd(animation: Animator) {
                mIsOpen=false
                mListener?.onBookCloseAnimationEnd(mBookId)
            }

            override fun onAnimationCancel(animation: Animator) {

            }

            override fun onAnimationRepeat(animation: Animator) {

            }
        })
        anim.start()
    }

    override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
        super.onLayout(changed, left, top, right, bottom)

    }


    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)

        if(mBitmap==null) return
        if(!mIsOpen) {
            canvas.drawColor(Color.TRANSPARENT)
            return
        }

        canvas.save()

        canvas.translate(mImgLeft-mImgLeft*mValue,mImgTop-mImgTop*mValue)
        //canvas.translate(mImgLeft.toFloat(),mImgTop.toFloat())

        canvas.scale(mMinScaleWidth+(mMaxScaleWidth-mMinScaleWidth)*mValue,mMinScaleHeight+(mMaxScaleHeight-mMinScaleHeight)*mValue)
        //canvas.scale(mMinScaleWidth,mMinScaleHeight)

        //draw open page
        canvas.drawRect(mPageRect,mPagePaint)

        mCamera.save()

        canvas.save()
        //cause axle in (0,0),so need to move middle when rotate
        canvas.translate(0f, -mImgWidth / 2)
        mCamera.rotateY(-180f*mValue)

        //fix distort and deformation
        mCamera.getMatrix(mCameraMatrix)
        mCameraMatrix.getValues(mMatrixValues)
        mMatrixValues[6]=mMatrixValues[6]/ScreenUtil.getDensity()
        mMatrixValues[7]=mMatrixValues[7]/ScreenUtil.getDensity()
        mCameraMatrix.setValues(mMatrixValues)
        canvas.concat(mCameraMatrix)

        canvas.translate(0f, mImgWidth / 2)

        canvas.drawBitmap(mBitmap!!,0f,0f,null)

        mCamera.restore()
        canvas.restore()
        canvas.restore()

    }



}